Software programming has changed over the years as computer programs have moved away from a sequential model of performing operations and toward a more asynchronous model wherein multiple operations of a single program may be performed substantially simultaneously. These computer programs are typically referred to as “event-driven” programs in that a user may initiate an event in the program and thereafter fail to take any other action with respect to that event for an indefinite period of time. As such, the program is in a waiting pattern in which the program takes no action with respect to this event until the user initiates such. During this interim, the user may initiate any number of other events in the computer program, take any number of other actions with respect to these other events, or perform no action.
Event-driven programs may perform any number of internal operations while waiting for the user to take action with respect to the initiated event or while the user is currently taking action with respect to that or any other event. That is, these programs do not execute tasks and perform operations in a sequential manner, but rather, in a concurrent manner wherein tasks and operations are performed substantially simultaneously with respect to each other. For instance, in a word processor having a graphical user interface, a user may select a control for formatting text in a document using a word processor application program. Meanwhile, between selection of the control and action by the user in the document utilizing the formatting function activated by the control, an auto save feature of the processor may be activated by an internal call initiated by the word processor application. The auto save and formatting operations thus execute logically in a concurrent manner, i.e., “concurrently,” with each other in the word processor.
The increasing use of distributed computing environments further illustrates the aforementioned transition in software programming. In distributed computing environments, multiple computer programs communicate with one another by passing messages over channels through which the programs are operably connected using some form of network connection, such a Local Area Network, Wide Area Network, the Internet, or the like. As such, a distributed computing environment may contain various application programs running on multiple computing systems. These application programs are operable to communicate with any number of application programs connected over the same network or possibly another network connection. As such, application programs, or instances thereof, in a distributed computing environment often await communications from other application programs. During this indefinite wait period, the application program may continue to perform operations, such as communicating with other application programs by sending and/or receiving messages. Consequently, application programs operating in a distributed computing environment perform tasks and operations in a concurrent manner that is similar to the event-driven application programs described above.
Collectively, application programs operating in a distributed computing environment and event-driven application programs may be referred to as “concurrent,” or “message-passing” applications. Although message-passing applications provide many functional advantages over sequential application programs, message-passing applications are not without problems. One common problem associated with message-passing application is deadlock. Deadlock is an error that may occur in many situations, but most frequently, in situations where an expected action for an operation never occurs. For instance, deadlock occurs when a message sent by a sender (caller) is never received by a receiver (callee). Likewise, deadlock occurs when a receiver waits for a message that is never actually sent by a sender.
Together with deadlock errors, asynchrony and nondeterminism introduced by the unpredictable nature of when message-passing applications may render a specific action make message-passing applications more difficult to write, debug, test and tune than applications operating in a sequential manner. Indeed, today's programming languages and tools currently offer little or no support for concurrent programming. Moreover, there are no current modeling techniques that accurately address the problems of deadlock errors described above.